package com.bw.http

import android.os.Environment
import androidx.annotation.RequiresFeature
import com.alibaba.android.arouter.launcher.ARouter
import com.bw.base.constants.ApiConst
import com.bw.base.constants.BaseConst
import com.bw.base.constants.RoutePath
import com.google.gson.Gson
import com.tencent.mmkv.MMKV
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.net.Proxy
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

/**
 * OkHttpClient管理类
 */
object OkHttpClientManager {
    /**
     * 普通的http请求客户端
     */
    val httpClientInstance: OkHttpClient by lazy {
        val builder = OkHttpClient.Builder().apply {
            connectTimeout(BaseConst.CONNECT_TIME_OUT, TimeUnit.SECONDS)
            readTimeout(BaseConst.READ_TIME_OUT, TimeUnit.SECONDS)
            writeTimeout(BaseConst.WRITE_TIME_OUT, TimeUnit.SECONDS)

            //设置接口请求日志拦截器

                addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))


            //Header参数拦截器
            addInterceptor(getHeaderInterceptor())

            //服务器异常拦截器
            addInterceptor(getServiceExceptionInterceptor())


            val storeFile = getExternalStoreFile()
            if (storeFile != null) {
                //10m缓存
                cache(Cache(storeFile, 10 * 1024 * 1024))
            }


        }
        builder.build()
    }

    /**
     * https请求客户端
     */
    val httpsClientInstance: OkHttpClient by lazy {
        OkHttpClient.Builder()
            .connectTimeout(BaseConst.CONNECT_TIME_OUT, TimeUnit.SECONDS)
            .readTimeout(BaseConst.READ_TIME_OUT, TimeUnit.SECONDS)
            .writeTimeout(BaseConst.WRITE_TIME_OUT, TimeUnit.SECONDS)
            .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            .addInterceptor(getServiceExceptionInterceptor())
            .addInterceptor(getHeaderInterceptor())
            .sslSocketFactory(sslSocketFactory, trustManager)
            .proxy(Proxy.NO_PROXY)
            .cache(getExternalStoreFile()?.let { Cache(it, 10 * 1024 * 1024) })
            .build()

    }

    //可以做长链接
    private val webSocketInstance: OkHttpClient by lazy {
        var wsOkBuilder = OkHttpClient.Builder().apply {
            pingInterval(10, TimeUnit.SECONDS)
        }

        wsOkBuilder.build()
    }

    /**
     * 发起 WebSocket请求
     */
    fun createWebSocketRequest(webSocketUrl: String, listener: WebSocketListener) {
        val requestBuilder = Request.Builder().apply {
            url(webSocketUrl)
        }

        webSocketInstance.newWebSocket(requestBuilder.build(), listener)
    }


    /**
     * Retrofit实例
     */
    val retrofitInstance: Retrofit by lazy {
        Retrofit.Builder().apply {
            baseUrl(ApiConst.BASE_URL)
            client(httpClientInstance)
            addConverterFactory(GsonConverterFactory.create())

        }.build()
    }

    /**
     * Retrofit Https实例
     */
    val retrofitHttpsInstance: Retrofit by lazy {
        Retrofit.Builder().apply {
            baseUrl(ApiConst.BASE_URL)
            client(httpsClientInstance)
            addConverterFactory(GsonConverterFactory.create())

        }.build()
    }


    private fun getExternalStoreFile(): File? {
        val externalStorageFile = Environment.getExternalStorageDirectory()
        if (externalStorageFile.exists()) return File(externalStorageFile, "park_network_cache")
        return null

    }


    /**
     * 请求头拦截器
     */
    private fun getHeaderInterceptor(): Interceptor {
        return object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {

                val builder = chain.request().newBuilder()


                val token = MMKV.defaultMMKV().decodeString(ApiConst.PARAM_TOKEN, "park2208")
                if (token != null) {
                    builder.header(ApiConst.PARAM_TOKEN, token)
                }
                val accessId = MMKV.defaultMMKV().decodeString(ApiConst.PARAM_ACCESS_ID, "")
                if (accessId != null) {
                    builder.header(ApiConst.PARAM_ACCESS_ID, accessId)
                }

                val request = builder.build()
                val response = chain.proceed(request)

                //验证token是否过期
                if (response.code == 403 || response.code == 401) {
                    ARouter.getInstance().build(RoutePath.PATH_LOGIN).navigation()
                }

                return response
            }
        }
    }


    /**
     * 服务器异常拦截器
     */
    private fun getServiceExceptionInterceptor(): Interceptor {
        return object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {


                val errorResponse = chain.proceed(chain.request())
                val builder = errorResponse.newBuilder()

                if (errorResponse.code == 500) {
                    val res = Res(500, "服务器异常", "请联系客服")

                    builder.body(
                        Gson().toJson(res)
                            .toResponseBody("application/json;charset=UTF-8".toMediaTypeOrNull())
                    )
                }

                return errorResponse
            }
        }
    }

    private val sslSocketFactory: SSLSocketFactory
        get() = try {
            val sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, arrayOf(), SecureRandom())
            sslContext.socketFactory
        } catch (e: Exception) {
            throw RuntimeException(e)
        }


    private val trustManager: X509TrustManager
        get() = object : X509TrustManager {
            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }

            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }

            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }
        }


    fun clearAllRequest() {

        httpClientInstance?.run {
            dispatcher?.run {
                cancelAll()         //取消所有的请求
                executorService.shutdown()      //关闭线程池
            }
            cache?.close()          //清除缓存
        }
        httpClientInstance?.run {
            dispatcher?.run {
                cancelAll()
                executorService.shutdown()
            }
            cache?.close()
        }
        webSocketInstance?.run {
            dispatcher?.run {
                cancelAll()
                executorService.shutdown()
            }
            cache?.close()
        }


    }

}